package org.visionlibrary.image.colormodel;

import java.awt.Point;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;

import javax.media.jai.TiledImage;

public class HSVConverter implements ColorConverter {

	@Override
	public float[] convert(TiledImage src, Point pixel) {
		return this.convert(src, pixel.x, pixel.y);
	}

	@Override
	public float[] convert(TiledImage src, int pixelx, int pixely) {
		float[] values = new float[src.getNumBands()];
		for (int i = 0; i < src.getNumBands(); i++)
			values[i] = src.getSampleFloat(pixelx, pixely, i);

		return convert(src.getColorModel(), values);
	}

	@Override
	public float[] convert(ColorModel cm, float[] values) {
		return convert(cm.getColorSpace(), values);
	}

	@Override
	public float[] convert(ColorSpace cs, float[] values) {
		switch (cs.getType()) {
		case ColorSpace.TYPE_RGB: {

			return convertFromTYPE_RGB(values);
		}

		default:
			return null;
		}
	}

	/**
	 * Converts color coded in RGB to HSV. RGB values are in range 0 .. 1.
	 * Returned HSV values re in range:<br />
	 * <ul>
	 * <li>Hue in range 0 .. 360</li>
	 * <li>Saturation in range 0 .. 1</li>
	 * <li>Value in range 0 .. 1</li>
	 * </ul>
	 * 
	 * @param values
	 *            RGB color, values in range 0 .. 1.
	 * @return Color converted to HSV.
	 */
	public float[] convertFromTYPE_RGB(float[] values) {
		float x, f, i;
		float hsv[] = new float[3];

		x = Math.min(Math.min(values[0], values[1]), values[2]);
		hsv[2] = Math.max(Math.max(values[0], values[1]), values[2]);
		if (x == hsv[2]) {
			hsv[0] = 0;
			hsv[1] = 0;
		} else {
			f = (values[0] == x) ? values[1] - values[2]
					: ((values[1] == x) ? values[2] - values[0] : values[0]
							- values[1]);
			i = (values[0] == x) ? 3 : ((values[1] == x) ? 5 : 1);
			hsv[0] = ((i - f / (hsv[2] - x)) * 60) % 360;
			hsv[1] = ((hsv[2] - x) / hsv[2]);
		}

		return hsv;
	}
}
